
Imports std

Public Module common

    Public Function strrplc2(ByRef str As String, ByVal trans() As pair(Of String, String), _
                             Optional ByVal carecase As Boolean = True) As String
        If Not isemptystring(str) Then
            Dim i As Int32
            If carecase Then
                For i = 0 To trans.Length() - 1
                    str = str.Replace(trans(i).first, trans(i).second)
                Next
            Else
                Dim j As Int32
                Dim lens As vector(Of Int32) = Nothing
                If Not trans Is Nothing Then
                    lens = New vector(Of Int32)
                    For i = 0 To trans.Length - 1
                        lens.push_back(strlen(trans(i).first))
                    Next
                    i = 0
                    While i < strlen(str)
                        For j = 0 To trans.Length() - 1
                            If strsame(str, i, trans(j).first, 0, lens(j), False) Then
                                str = strleft(str, i) + trans(j).second + strright(str, strlen(str) - i - lens(j))
                                i += strlen(trans(j).second)
                                Exit For
                            End If
                        Next
                        If j = trans.Length() Then
                            i += 1
                        End If
                    End While
                End If
            End If
        End If

        Return str
    End Function

    Public Function strrplc2(ByRef str As String, ByVal trans As vector(Of pair(Of String, String)), _
                             Optional ByVal carecase As Boolean = True) As String
        Return strrplc2(str, trans.data(), carecase)
    End Function

    Public Function fitfilterSet(ByVal filterSet As vector(Of String), ByVal str As String _
                                 , Optional ByVal careCase As Boolean = False) As Boolean
        Return stringfilter.fitfilterList(filterSet, str, careCase)
    End Function

    Public Function fitfilter(ByVal filter As String, ByVal str As String _
                              , Optional ByVal careCase As Boolean = False) As Boolean
        Dim rtn As Int32
        Dim extCode As Boolean = False
        rtn = stringfilter.fitfilter(filter, str, careCase)
        If rtn = stringfilter.fitUndertermind Then
            If strlen(filter) > 0 AndAlso filter(0) = stringfilter.cutSign Then
                extCode = True
            Else
                extCode = False
            End If
        Else
            extCode = (rtn = stringfilter.fitTrue)
        End If

        Return extCode
    End Function
End Module

Namespace stringfilter
    Public Module stringfilter
        Public Const fitTrue As Byte = 1
        Public Const fitFalse As Byte = 2
        Public Const fitUndertermind As Byte = 0
        Public Const cutSign As Char = character.minusSign
        Public Const addSign As Char = character.plusSign
        Public Const multiCharSign As Char = character.multiplicationSign
        Public Const singleCharSign As Char = character.questionMark

        Friend Function fitfilterList(ByVal filterSet As vector(Of String), ByVal name As String, _
                                      Optional ByVal careCase As Boolean = False) As Boolean
            Dim i As Int32
            Dim result As Int32
            Dim fited As Boolean = False

            For i = 0 To filterSet.size() - 1
                result = fitfilter(filterSet(i), name, careCase)
                If result = fitFalse Then
                    fited = False
                ElseIf (result = fitTrue) Then
                    fited = True
                End If
            Next

            Return fited
        End Function

        Private Function fitfilterLite(ByVal definition As String, ByVal name As String, _
                                       Optional ByVal careCase As Boolean = False) As Boolean
            Dim i As Int32 = 0
            Dim j As Int32 = 0
            Dim definitionLen As Int32 = strlen(definition)
            Dim nameLen As Int32 = strlen(name)
            Dim rtn As Boolean

            definition += character.null
            name += character.null
            While (i < definitionLen AndAlso j < nameLen)
                If definition(i) = multiCharSign Then
                    i += 1
                    While (definition(i) = multiCharSign)
                        i += 1
                    End While
                    rtn = False
                    While (j <= nameLen)
                        While j <= nameLen
                            If (careCase AndAlso name(j) <> definition(i)) _
                                OrElse (Not careCase AndAlso Char.ToLower(name(j)) <> Char.ToLower(definition(i))) Then
                                j += 1
                            Else
                                Exit While
                            End If
                        End While

                        rtn = fitfilterLite(strmid(definition, i, definitionLen - i), _
                                            strmid(name, j, nameLen - j), careCase)
                        If rtn Then
                            Exit While
                        Else
                            j += 1
                        End If
                    End While

                    If rtn Then
                        i = definitionLen
                        j = nameLen
                    End If
                    Exit While
                ElseIf definition(i) = singleCharSign Then
                    i += 1
                    j += 1
                Else
                    If ((careCase AndAlso definition(i) = name(j)) Or _
                     (Not careCase AndAlso Char.ToLower(definition(i)) = Char.ToLower(name(j)))) Then
                        i += 1
                        j += 1
                    Else
                        Exit While
                    End If
                End If
            End While

            While definition(i) = multiCharSign
                i += 1
            End While
            If i < definitionLen OrElse j < nameLen Then
                Return False
            Else
                Return True
            End If
        End Function

        Friend Function fitfilter(ByVal definition As String, ByVal name As String, _
                                  Optional ByVal careCase As Boolean = False) As Byte
            If strlen(definition) > 0 AndAlso definition(0) = cutSign Then
                If (fitfilterLite(strmid(definition, 1), name, careCase)) Then
                    Return fitFalse
                Else
                    Return fitUndertermind
                End If
            Else
                Dim offside As Byte = 0
                If strlen(definition) > 0 AndAlso definition(0) = addSign Then
                    offside = 1
                End If
                If (fitfilterLite(strmid(definition, offside), name, careCase)) Then
                    Return fitTrue
                Else
                    Return fitUndertermind
                End If
            End If
        End Function
    End Module
End Namespace
